IList
IList — Indexed Access Collections
"Use IList
when you need random access by index, or when Insert/RemoveAt operations are required."
❌ Bad example:
public IEnumerable<Trade> GetRecentTrades()
{
return _trades.OrderByDescending(t => t.Timestamp).Take(10);
}
// Caller
public void DisplayLastTrade(IEnumerable<Trade> trades)
{
var lastTrade = trades.Last(); // enumerates entire sequence
Console.WriteLine(lastTrade.Symbol);
}
Using .Last() on IEnumerable
✅ Good example:
public IList<Trade> GetRecentTrades()
{
return _trades.OrderByDescending(t => t.Timestamp).Take(10).ToList();
}
// Caller
public void DisplayLastTrade(IList<Trade> trades)
{
var lastTrade = trades[trades.Count - 1]; // O(1) indexed access
Console.WriteLine(lastTrade.Symbol);
}
👉 IList
🔥 When Insert/RemoveAt matters:
public class OrderBook
{
public IList<Order> BuyOrders { get; } = new List<Order>();
public void InsertOrderAtPrice(Order order)
{
// Binary search to find insertion point
int index = BuyOrders.BinarySearch(order, new PriceComparer());
if (index < 0) index = ~index;
BuyOrders.Insert(index, order); // insert at specific position
}
}
👉 IList
🔥 Avoiding unnecessary copies:
// ❌ Bad: forces caller to know concrete type
public List<decimal> CalculatePrices(List<decimal> basePrices)
{
for (int i = 0; i < basePrices.Count; i++)
basePrices[i] *= 1.05m;
return basePrices;
}
// ✅ Good: accepts interface, returns interface
public IList<decimal> CalculatePrices(IList<decimal> basePrices)
{
for (int i = 0; i < basePrices.Count; i++)
basePrices[i] *= 1.05m;
return basePrices;
}
👉 Accepting IList
💡 In trading systems:
- Use IList
for order books where indexed access is critical for price levels. - Enable efficient batch processing with index-based loops (faster than foreach for large arrays).
- Prefer IEnumerable
unless random access is genuinely needed—narrower contract.
---
Questions & Answers
Q: What's the difference between ICollection
A: IList
Q: Does IList
A: Not strictly. List
Q: Should I return IList
A: Only if callers need indexed access or Insert/RemoveAt. Otherwise, IEnumerable
Q: Can IList
A: Yes. Arrays are fixed-size, so Add/Remove throw NotSupportedException. Check IsReadOnly before assuming mutability. Prefer IReadOnlyList
Q: How does IList
A: Arrays implement IList
Q: When should I use for vs foreach with IList
A: Use for (int i = 0; i < list.Count; i++) when you need the index or modify elements by index. Use foreach for clarity when index isn't needed.
Q: What's the performance of IndexOf() on IList
A: O(n) for List
Q: Can I pass an array as IList
A: Yes. Arrays implement IList
Q: How do I mock IList
A: Use List
Q: What happens if I access IList
A: Throws IndexOutOfRangeException (arrays) or ArgumentOutOfRangeException (List